<?php

namespace App\Services;

use App\Exceptions\CustomException;
use App\Models\Active;
use App\Models\Bank;
use App\Models\BankReceiveAccount;
use App\Models\MoneyDeposit;
use App\Models\PayScene;
use App\Models\PayVendor;
use App\Models\PayVendorScene;
use App\Models\UserAuthStatus;
use App\Models\UserLevel;
use App\Models\WebsiteDocument;
use common\enum\ActiveEnum;
use common\enum\MoneyDepositEnum;
use common\enum\WebsiteDocumentEnum;
use common\utils\RedisKeys;
use common\utils\RSACrypt;
use common\utils\SysCode;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use App\Models\Order;

//充值存款相关service方法
class RechargeService
{
    const RECHARGE_TYPE_OFFLINE = 1;//线下充值 支付类型（前端调用）
    const RECHARGE_TYPE_ONLINE = 3;//线上充值-聚合支付 支付类型（前端调用）
    const RECHARGE_TYPE_ONLINEPAY = 4;//线上充值-网银支付 支付类型（前端调用）

    const ONLINEPAY_SCENE_LIST = ['onlinepay', 'onlinepay_wap'];//网银支付场景 非聚合支付类型（网银支付）， 支付类型type = 4
    /**
     * 根据支付代码，获取支付服务类
     * @param $code
     */
    public static function getRechargeService($code){
        $className = 'App\Services\Recharge\Recharge' . ucfirst(strtolower($code)) . 'Service';
        if (class_exists($className)) {
            return new $className();
        } else {
            throw new CustomException('recharge service not exists!');
        }
    }
    
    /**
     * 获取充值信息
     * @param string $type
     */
    public static function getRecharge($user, $pf=1){
        //获取是否允许优惠
        $userAuthStatus = UserAuthStatus::where(['user_id' => $user['id']])->first();
        $isRefuseCoupon = (!empty($userAuthStatus) && $userAuthStatus['is_refuse_coupon'] == 1) ? true : false;
        //会员禁止优惠
        if(!$isRefuseCoupon){
            //充值優惠活動
            list($activeOffline, $activeOnline, $withdrawType, $withdrawVal) = static::getActiveInfo();
        }

        //用户层级信息
        $userLevelInfo = UserLevelService::getInfoById($user['level_id']);

        //线上存款 充值方式列表
        $offlinePay = static::getOfflinePay($user, $pf);

        //线上充值信息
        $onlinePay = static::getOnlinePay($user, $pf, $userLevelInfo);

        return [
            //线下公司入款信息
            'offline_pay' => [
                'receive_bank' => $offlinePay['receive_bank'], //厅主设置的存款账户列表
                'bank' => $offlinePay['bank'],//可用的银行列表
                'active' => $activeOffline ?? [],//优惠活动
                'remark' => $offlinePay['remark'],//线下充值提示信息
                'type' => static::RECHARGE_TYPE_OFFLINE,//支付类型
                'info' => [//充值限额等信息
                    'deposit_min' => amount_format($userLevelInfo['deposit_offline_min_limit']),//最小存款金额
                    'deposit_max' => amount_format($userLevelInfo['deposit_offline_max_limit']),//最大存款金额
                    'withdraw_rate' => $userLevelInfo['deposit_offline_validbet_multi'],//用户层级设置-打码量倍数 （充值金额 * 倍数）
                    'withdraw_type' => $withdrawType ?? '',//优惠活动设置-打码量参数类型
                    'withdraw_val' => $withdrawVal ?? 0,//优惠活动设置-值
                ],
            ],
            //线上存款 充值方式列表
            'online_pay' => [
                'list' => $onlinePay['list'], //充值方式列表 (包含： 提示信息（pc使用）)
                'active' => $activeOnline ?? [],//优惠活动
                'remark' => $onlinePay['remark'],//线上充值h5端提示信息（pc端根据list不同的充值渠道给提示）
                'info' => [//充值限额等信息
                    'deposit_min' => amount_format($userLevelInfo['deposit_online_min_limit']),//最小存款金额
                    'deposit_max' => amount_format($userLevelInfo['deposit_online_max_limit']),//最大存款金额
                    'withdraw_rate' => $userLevelInfo['deposit_online_validbet_multi'],//用户层级设置-打码量倍数 （充值金额 * 倍数）
                    'withdraw_type' => $withdrawType ?? '',//优惠活动设置-打码量参数类型
                    'withdraw_val' => $withdrawVal ?? 0,//优惠活动设置-值
                ],
            ],

        ];
    }

    /**
     * 获取线下充值信息
     * @param $user
     * @param string $type
     */
    public static function getOfflinePay($user, $pf){
        //公司收款銀行賬戶
        $receiveBank = BankReceiveAccount::select(['id', 'name', 'card', 'address','once_min_limit','once_max_limit','qrcode', 'remark'])
                        ->where(['status' => 1])->get()->toArray();
        if(empty($receiveBank)){
            return [];
        }
        RSACrypt::rsaPatch($receiveBank);
        amount_format_array($receiveBank, ['once_min_limit','once_max_limit']);//格式化金額字段

        //可用的銀行卡列表
        $bank = Bank::select(['id','code','name','h5_logo', 'logo'])->where(['status' => 1, 'is_online' => 0])->get()->toArray();

        //线下充值提示信息（h5使用）
        $remark = static::getRemark($pf, WebsiteDocumentEnum::TYPE_OFFLINE_DEPOSIT);

        return [
            'receive_bank' => $receiveBank, //厅主设置的存款账户列表
            'bank' => $bank,//可用的银行列表
            'remark' => $remark,//充值文案
        ];
    }

    /**
     * 获取线上充值信息
     * @param $user
     * @param $pf
     */
    public static function getOnlinePay($user, $pf, $userLevelInfo){

        $payList = static::getPayVendorSceneList($user, $pf, $userLevelInfo);
        $remark = static::getRemark($pf, WebsiteDocumentEnum::TYPE_ONLINE_DEPOSIT);
        return [
            'list' => $payList,
            'remark' => $remark,
        ];
    }
    /**
     * 获取存款文案
     * @param $pf  1pc, 2h5
     * @param $type 301微信入款,302qq入款,303公司入款,304银联,305支付宝入款,306线下入款,307线上入款,
     */
    public static function getRemark($pf, $type){
        //线上，线下充值类型， 取h5文案
        if(in_array($type, [WebsiteDocumentEnum::TYPE_OFFLINE_DEPOSIT, WebsiteDocumentEnum::TYPE_ONLINE_DEPOSIT])){
            $pf = 2;
        }
        //todo 取全局设置的时候， 需要根据原本的类型得到属于的平台
        $data = WebsiteDocument::where(['platform' => $pf, 'type' => $type, 'status' => 1, 'category' => WebsiteDocumentEnum::CATEGORY_DEPOSIT ])->first();
        return $data ? $data->toArray()['content'] : '';
    }
    /**
     * 获取优惠活动信息
     * @return array(綫下優惠活動信息， 綫上活動信息)
     * {
    "issue_cycle": "day",
    "rule": {
    "companyCheck": ["first"],
    "onlineCheck": ["again"],
    "checkDeposit": {
    "companyCheck": ["first"],
    "onlineCheck": ["again"]
    },
    "company": {
    "first": [{
    "money": 1000,
    "prize": 2000,
    "prize1": "2",
    "prize2": "",
    "type": "1",
    "upper_limit": ""
    }, {
    "money": 2000,
    "type": "2",
    "prize": 1000,
    "prize1": "",
    "prize2": "1",
    "upper_limit": ""
    }],
    "again": [{
    "money": "",
    "prize": "",
    "prize1": "",
    "prize2": "",
    "type": "1",
    "upper_limit": ""
    }]
    },
    "online": {
    "first": [{
    "money": "",
    "prize": "",
    "prize1": "",
    "prize2": "",
    "type": "1",
    "upper_limit": ""
    }],
    "again": [{
    "money": 2000,
    "prize": 1000,
    "prize1": "1",
    "prize2": "",
    "type": "1",
    "upper_limit": ""
    }, {
    "money": 3000,
    "type": "2",
    "prize": 2000,
    "prize1": "",
    "prize2": "2",
    "upper_limit": 3000
    }]
    }
    }
    }
     */
    public static function getActiveInfo($activeID=NULL){
        $noActive = [
            'id' => 0,
            'title' => '不参与优惠活动',
        ];
        //获取当前有效的充值优惠活动 时间倒序第一条
        $active = static::getRechargeActive($activeID);
        if(empty($active['rule'])){//优惠活动配置异常
            throw new CustomException(SysCode::ACTIVE_STATUS_ERROR, '优惠活动获取失败');
        }

        $withdrawType = $active['withdraw_require_type'];//提款要求(1:优惠金额的倍数, 2:有效投注金额, 0:无)
        $withdrawVal = $withdrawType == 1 ? ($active['withdraw_require_times'] ?? 0) : amount_format($active['withdraw_require_validbet'] ?? 0);//提款要求--金额or投注流水  金额单位：分， 需转换为：元
        $ruleArr = json_decode($active['rule'], true);//优惠规则
        if(empty($ruleArr) || json_last_error() || empty($ruleArr['rule']))
        {
            throw new CustomException('获取优惠活动异常！');
        }
        $ruleArr = $ruleArr['rule'];

        //是否首存
        $isNewDeposit = static::isNewDeposit();
        $depositType = $isNewDeposit ? 'first' : 'again';
        //公司入款-线下充值
        $offlineRule = $ruleArr['company'] ?? [];
        if($offlineRule){
            $offlineRule = $offlineRule[$depositType];
            //格式化充值活动规则
            foreach ($offlineRule as & $r){
                $r['type'] = (int)$r['type'];//优惠类型  1 prize为优惠金额 2 prize为优惠倍数（float）
                $r['money'] = amount_format($r['money']);
                $r['prize'] = $r['type'] == ActiveEnum::WITHDRAW_REQUIRE_TYPE_MULTI ? floatval($r['prize']) : amount_format($r['prize']);
                //优惠上线， 只有type=2的时候存在
                $r['upper_limit'] = $r['type'] == ActiveEnum::WITHDRAW_REQUIRE_TYPE_MULTI ? amount_format($r['upper_limit']) : 0;
            }
        }

        //线上充值
        $onlineRule = $ruleArr['online'] ?? [];
        if($onlineRule){
            $onlineRule = $onlineRule[$depositType];
            //格式化充值活动规则
            foreach ($onlineRule as & $r){
                $r['type'] = (int)$r['type'];//优惠类型  1 prize为优惠金额 2 prize为优惠倍数（float）
                $r['money'] = amount_format($r['money']);
                $r['prize'] = $r['type'] == ActiveEnum::WITHDRAW_REQUIRE_TYPE_MULTI ? floatval($r['prize']) : amount_format($r['prize']);
                //优惠上线， 只有type=2的时候存在
                $r['upper_limit'] = $r['type'] == ActiveEnum::WITHDRAW_REQUIRE_TYPE_MULTI ? amount_format($r['upper_limit']) : 0;
            }
        }

        //格式化活动提款要求参数
        $withdrawType = $active['withdraw_require_type'];//1:优惠金额的倍数, 2:有效投注金额, 0:无
        $withdrawVal = $withdrawType == ActiveEnum::WITHDRAW_REQUIRE_TYPE_MULTI ? floatval($active['withdraw_require_times']) : amount_format($active['withdraw_require_validbet']);

        return [
            //线下
            [
                $noActive,
                [
                    'id' => $active['id'],
                    "title" => $active['name'],
                    'rule' => $offlineRule,
                ]
            ],
            //线上
            [
                $noActive,
                [
                    'id' => $active['id'],
                    "title" => $active['name'],
                    'rule' => $onlineRule,
                ]
            ],
            //提款要求类型
            $withdrawType,
            //提款要求的值
            $withdrawVal
        ];
    }

    /**
     * 获取用户有效的充值活动信息
     * @param null $activeID
     * @return array
     */
    public static function getRechargeActive($activeID=NULL){
        $nowDate = date('Y-m-d H:i:s');
        $active = Active::select(['id', 'name', 'title', 'type_id', 'rule','withdraw_require_type', 'withdraw_require_validbet', 'withdraw_require_times'])
            ->where(
                [
                    'template_id' => ActiveEnum::ACTIVE_RECHARGE_OFFER,
                    'status' => ActiveEnum::STATUS_OPEN
                ]
            )
            ->where('begin_time', '<=', $nowDate)
            ->where('end_time', '>', $nowDate);
        if($activeID > 0){
            $active->where(['id' => $activeID]);
        }
        $info = $active->orderBy('begin_time', 'DESC')->first();
        if(empty($info)){
            return [];
        }
        return $info->toArray();
    }
    /**
     * 是否首存
     */
    public static function isNewDeposit($user=null){
        if(is_null($user)){
            $user = Auth::user();
        }
        return MoneyDeposit::where(['user_id' => $user['id'],'status' => 1, 'is_first' => 1])->first() ? false : true;
    }
    /**
     * 获取线上充值可用的支付方式列表（需要区分聚合支付，非聚合支付（网银，快捷））
     * 根据厅后台开启的支付，用户层级 筛选
     * @param $user 登陆信息
     * @param string $type 1 pc 2 h5
     */
    public static function getPayVendorSceneList($user, $pf=1, $userLevelInfo = []){
         //用户层级
        $levelID = $user['level_id'];
        //可用支付通道
        $list = DB::table('pay_vendor_scene as pvs')->leftJoin('pay_vendor as pv', 'pvs.vendor_id','=', 'pv.id')
            ->where(['pvs.status' => 1])
            ->whereRaw("find_in_set({$levelID}, pvs.level_ids)")
            ->select(['pvs.scene','pvs.once_min_limit', 'pvs.once_max_limit', 'pv.code', 'pv.name', ])
            ->get()->toArray();
        //筛选pc 或 h5通道
        foreach ($list as $key => $val){
            $val = (array)$val;
            if($pf == 1){//pc
                if(strpos($val['scene'], '_wap') !== false){
                    unset($list[$key]);
                }
            }else{//h5
                if(strpos($val['scene'], '_wap') === false){
                    unset($list[$key]);
                }
            }
        }
        $list = array_values($list);
        //支付场景
        $payScene = PayScene::select(['name', 'scene'])->get();
        $payScene = build_relation_array($payScene, 'scene');

        //格式化
        foreach($list as & $val){
            $val = (array)$val;
            $sceneSplit = explode('_', $val['scene']);
            $val['name'] = trim($payScene[$val['scene']]['name'], 'WAP');//支付分类名称
            $val['logo'] = config('app.upload_server') . '/uploads/bank/' . $sceneSplit[0] . '.png';//支付图片
            $documentType = '';
            if(strpos($val['scene'], 'unionpay') !== false){
                $documentType = '304';//银联入款
            }elseif(strpos($val['scene'], 'wx') !== false){
                $documentType = '301';//微信入款
            }elseif(strpos($val['scene'], 'alipay') !== false){
                $documentType = '305';//支付宝入款
            }elseif(strpos($val['scene'], 'qq') !== false){
                $documentType = '302';//qq入款
            }
            $val['remark'] = $documentType ? static::getRemark($pf, $documentType) : '';
            if(in_array($val['scene'], static::ONLINEPAY_SCENE_LIST)){//网银支付类型
                $val['type'] = static::RECHARGE_TYPE_ONLINEPAY;
//                $val['bank_list'] = static::getRechargeService($val['code'])::bankList();//网银支付， 前端支持银行卡
                $val['bank_list'] = RpcService::rpcRequest('/payment/bankList', 'GET', ['code' => $val['code']]);//网银支付， 前端支持银行卡
            }else{//线上聚合支付类型
                $val['type'] = static::RECHARGE_TYPE_ONLINE;//线上充值-聚合支付 支付类型
            }
        }

        //支付方式前端排序需求
        if ($pf == 1) {//pc
            $sortArr = ['wx', 'alipay', 'qq', 'jingdong', 'baidu', 'suning', 'unionpay', 'onlinepay', 'quickpay'];
        } else {//h5
            $sortArr = ['wx_wap', 'alipay_wap', 'qq_wap', 'jingdong_wap', 'baidu_wap', 'suning_wap', 'unionpay_wap', 'onlinepay_wap', 'quickpay_wap'];
        }
        $sortList = [];
        foreach ($sortArr as $v) {
            foreach ($list as $vv) {
                if ($vv['scene'] == $v) {
                    $sortList[] = $vv;
                }
            }
        }

        //每个支付类型的最小，最大支付金额 (根据场景的最小最大限额判断处理)
        //充值成功率高的范围：取层级限额和支付限额范围中小的范围

        $minMoney = null;//普通成功率-最低限额
        $maxMoney = null;//普通成功率-最高限额
        $highMinMoney = null;//高成功率-最低限额
        $highMaxMoney = null;//高成功率-最高限额
        $limitArr = [];//限额列表
        foreach ($sortList as $val){
            $scene = $val['scene'];
            if(!isset($limitArr[$scene]['once_min_limit'])){
                $limitArr[$scene]['once_min_limit'] = $val['once_min_limit'];
            }
            if(!isset($limitArr[$scene]['once_max_limit'])){
                $limitArr[$scene]['once_max_limit'] = $val['once_max_limit'];
            }
            if(!isset($limitArr[$scene]['high_once_min_limit'])){
                $limitArr[$scene]['high_once_min_limit'] = $val['once_min_limit'];
            }
            if(!isset($limitArr[$scene]['high_once_max_limit'])){
                $limitArr[$scene]['high_once_max_limit'] = $val['once_max_limit'];
            }
            $limitArr[$scene]['once_min_limit'] = min($limitArr[$scene]['once_min_limit'], $val['once_min_limit']);
            $limitArr[$scene]['once_max_limit'] = max($limitArr[$scene]['once_max_limit'], $val['once_max_limit']);
            $limitArr[$scene]['high_once_min_limit'] = max($limitArr[$scene]['high_once_min_limit'], $val['once_min_limit']);
            $limitArr[$scene]['high_once_max_limit'] = min($limitArr[$scene]['high_once_max_limit'], $val['once_max_limit']);
        }
//        return $limitArr;
        //普通成功率， 高成功率 限额赋值
        foreach($sortList as & $val){
            $scene = $val['scene'];
            if(!in_array($val['scene'], static::ONLINEPAY_SCENE_LIST)) {//聚合支付类型
                //普通成功率限额
                $val['once_min_limit'] = max($userLevelInfo['deposit_online_min_limit'], $limitArr[$scene]['once_min_limit']);
                $val['once_max_limit'] = min($userLevelInfo['deposit_online_max_limit'], $limitArr[$scene]['once_max_limit']);

                //高成功率限额
                $val['high_once_min_limit'] = max($userLevelInfo['deposit_online_min_limit'],$limitArr[$scene]['high_once_min_limit']);
                $val['high_once_max_limit'] = min($userLevelInfo['deposit_online_max_limit'],$limitArr[$scene]['high_once_max_limit']);

            }else{//网银支付
                //普通成功率限额 高成功率限额
                $val['once_min_limit'] = $val['high_once_min_limit'] = max($userLevelInfo['deposit_online_min_limit'], $val['once_min_limit']);
                $val['once_max_limit'] = $val['high_once_max_limit'] = min($userLevelInfo['deposit_online_max_limit'], $val['once_max_limit']);
            }

            //普通成功率金额大小值异常 则金额为用户层级大小值
            if($val['once_min_limit'] > $val['once_max_limit']){
                $val['once_min_limit'] = $userLevelInfo['deposit_online_min_limit'];
                $val['once_max_limit'] = $userLevelInfo['deposit_online_max_limit'];
            }
            //高成功率金额大小值异常 则金额为空
            if($val['high_once_min_limit'] > $val['high_once_max_limit']){
                $val['high_once_min_limit'] = 0;
                $val['high_once_max_limit'] = 0;
            }
            //限额单位转换
            $val['once_min_limit'] = amount_format($val['once_min_limit']);
            $val['once_max_limit'] = amount_format($val['once_max_limit']);
            $val['high_once_min_limit'] = amount_format($val['high_once_min_limit']);
            $val['high_once_max_limit'] = amount_format($val['high_once_max_limit']);
        }
        return $sortList;
    }


    /**
     * 充值提交 - 线上线下
     * @param $user
     * @param $params
     * @return array
     */
    public static function putRecharge($user, $params){
        //参数定义
        $type = $params['type'];//充值方式
        $money = amount_format($params['money'], true);//充值金额 - 元
        $scene = $params['scene'] ?? '';//线上支付-场景
        $code = $params['code'] ?? '';//线上支付-支付渠道码
        $bankCode = $params['bank_code'] ?? '';//网银充值 - 银行code

        $receiveBankID = $params['receive_bank_id'] ?? 0;//收款账户id
        $payBankID = $params['pay_bank_id'] ?? 0;//线下-银行列表id 对应 bank id
        $payBankCard = $params['pay_bank_card'] ?? '';//线下-用户入款卡号
        $payBankName = $params['pay_name'] ?? '';//线下-用户入款人名称
        $payRemark = $params['remark'] ?? '';//存款说明

        $activeID = $params['active_id'] ?? '';//活动ID
        $activeType = $params['active_type'] ?? 0;//活动优惠类型
        $activeMoney = amount_format($params['active_money'] ?? 0, true);//活动优惠金额
        $activePrize = $params['active_prize'] ?? 0;
        $upperLimit = $params['upper_limit'] ?? 0;
        $activePrize = $activeType == ActiveEnum::WITHDRAW_REQUIRE_TYPE_MULTI ? $activePrize : amount_format($activePrize, true);//活动参数， type=1表示优惠百分比（30 表示 money * 30%） type=2 表示优惠固定金额
        $upperLimit = $activeType == ActiveEnum::WITHDRAW_REQUIRE_TYPE_MULTI  ? $upperLimit : amount_format($upperLimit, true);//活动优惠金额上限

        $source = $params['source'] ?? 1;//支付来源，1 pc 2 h5  3 ios 4 Android
        $ip = $_SERVER['REMOTE_ADDR'];//ip
        $remark = $params['remark'] ?? '';//存款备注

        //线下充值参数检验
        if($params['type'] == static::RECHARGE_TYPE_OFFLINE && empty($params['receive_bank_id'])){
            return error_exit(SysCode::INVALID_ARGUMENT, '收款账户不能为空');
        }
        //存款金额验证
        if(!is_numeric($money) || $money <=0){
            error_exit(SysCode::RECHARGE_MONEY_ERROR, '充值金额异常');
        }
        //用户层级信息 充值金额限制（线上线下） 用户层级限制
        static::checkUserLevelRechargeLimit($type, $user['level_id'], $money);

        //优惠活动验证 验证活动是否改变
        $activeInfo = static::getActiveInfo($activeID);
        static::checkActive($type, $user, $activeID, $activeInfo, $activeType, $activeMoney, $activePrize, $upperLimit);

        //调用第三方充值 返回支付信息
        switch($type){
            case static::RECHARGE_TYPE_OFFLINE:
                return static::handelOfflineRecharge();//线下存款
            case static::RECHARGE_TYPE_ONLINE:
            case static::RECHARGE_TYPE_OFFLINE:
                return static::handelOnlineRecharge($user, $scene, $money, $activeID, $activeInfo, $code, $bankCode, $ip, $source, $remark);//线上充值， 网银充值
        }

        //根据类型处理 1 线下 3 线上 4 网银
        //1
        //2 先生成存款单， 然后调用第三方支付， 如果存在错误则保存下来
        //4 返回支付信息

    }

    protected static function handelOnlineRecharge($user, $scene, $money, $activeID, $activeInfo, $code, $bankCode, $ip, $source='', $remark=''){
        $requestOverTime = 10;//请求超时时间(单位为秒)
        $orderNumber = recharge_trade_no();//系统支付订单号
        $startTime = time();//处理开始时间

        //获取优惠和打码量信息
        $couponWithDrawData = static::couponAndWithdraw($user, $money, static::RECHARGE_TYPE_ONLINE, $activeID, $activeInfo);

        //先生成存款订单（状态默认为未处理，请求结束后需要更改状态）
        $depositModel = [
            'order_number' => $orderNumber,
            'user_id' => $user['id'],
            'name' => $user['username'],
            'amount' => $money,
            'recharge_time' => date('Y-m-d H:i:s', $startTime),//交易时间
            'is_online' => MoneyDepositEnum::IS_ONLINE_TRUE,//充值类型， 线上
            'is_first' => static::isNewDeposit($user),
            'active_id' => (int)$activeID,//优惠活动ID
            'ip' => $ip,//存款IP
            'status' => MoneyDepositEnum::STATUS_PENDING,//未处理
            'remark' => $remark,//备注

            'coupon_amount' => $couponWithDrawData['coupon_amount'],//优惠金额
            'coupon_validbet' => $couponWithDrawData['coupon_validbet'],//优惠要求打码量，提款时的优惠费用相关
            'withdraw_validbet' => $couponWithDrawData['withdraw_validbet'],//存款要求打码量(常态打码量),存款x流水倍数，提款时的行政费相关
            'active_name' => $activeInfo[1][1]['title'] ?? '',//优惠名称


            'pay_number' => '',//支付号(外部/第三方交易号) 调用第三方成功后保存
            'online_pay_id' => 0,//与 pay_vendor 的 id 对应 初始化为0, 调用第三方成功后保存

            'remark' => $remark ? $remark : ($activeID > 0 ? '参加优惠' : ''),//备注
        ];
        $depositID = DB::table('money_deposit')->insert($depositModel);
        if(!$depositID){
            error_exit(SysCode::RECHARGE_SAVE_ERROR, '保存充值失败');
        }


        //根据支付场景, 获取可用的支付渠道列表 (每日最大存款总额 总存款限制)
        $dayRechargeAmount = (array)DB::table('report_money_log')->select(DB::raw('sum(deposit_online_amount) as total'))
            ->where(['user_id' => $user['id']])
            ->where(['date' => date('Y-m-d')])->first();
        $dayRechargeAmount = $dayRechargeAmount ? (int)$dayRechargeAmount['total'] : 0;

        $totalRechargeAmount = (array)DB::table('report_money_log')->select(DB::raw('sum(deposit_online_amount) as total'))
            ->where(['user_id' => $user['id']])
            ->first();
        $totalRechargeAmount = $totalRechargeAmount ? (int)$totalRechargeAmount['total'] : 0;
        $list = DB::table('pay_vendor_scene as pvs')->leftJoin('pay_vendor as pv', 'pvs.vendor_id','=', 'pv.id')
            ->where(['pvs.status' => 1])
            ->where(['pvs.scene' => $scene])
            ->where('pvs.day_max_limit', '>', $dayRechargeAmount )
            ->where('pvs.total_max_limit', '>', $totalRechargeAmount )
            ->select(['pvs.scene','pvs.once_min_limit', 'pvs.once_max_limit', 'pv.code', 'pv.name', 'pv.id'])
            ->orderBy('pvs.sort');

        //网银支付
        if(in_array($scene, static::ONLINEPAY_SCENE_LIST)){

        }
        if(count($list) == 0){
            error_exit(SysCode::RECHARGE_NOT_MATCHED_CHANNEL, '没有可用的支付渠道');
        }
        echo 2;exit;
        $list = $list->toArray();


    }

    /**
     * 获取优惠和打码量信息
     * 打码量: 参与优惠活动使用优惠活动定义的打码量规则， 未参与活动则使用用户等级定义的打码量规则
     * @param $user
     * @param $money
     * @param $activeID
     * @param $type 1 线下 2 线上
     * @return array
     * [
        'coupon_money' => $coupon_money, //优惠金额
        'couponId' => $couponId, // 活动id ？
        'withdraw_bet' => $withdraw_bet, //打码量
        'isNew' => $isNew, //是否首存
        'withdraw_bet_coupon' => $withdraw_bet_coupon //优惠提款打码量
        ]
     */
    public static function couponAndWithdraw($user, $money, $type, $activeID, $activeInfo){
        //是否首存
        $isNewDeposit = static::isNewDeposit($user);
        $couponPrize = $withdrawCouponValidbet = $withdrawValidbet = 0;

        //参加优惠活动， 计算优惠金额
        if($activeID > 0){
            list($activeOffline, $activeOnline, $withdrawType, $withdrawVal) = $activeInfo;
            //获取活动规则 (注意规则中金额为元， 需要格式化处理)
            $rule = $type == static::RECHARGE_TYPE_OFFLINE ? $activeOffline[1]['rule'] : $activeOnline[1]['rule'];
            $ruleIdx = -1;
            $ruleMoney = 0;
            foreach ($rule as $key => $val){
                $moneyMark = amount_format($val['money'], true);
                if($money >= $moneyMark && $ruleMoney <=  $moneyMark){
                    $ruleIdx = $key;
                    $ruleMoney = $moneyMark;
                }
            }

            if($ruleIdx >= 0){
                if($rule[$ruleIdx]['type'] == ActiveEnum::WITHDRAW_REQUIRE_TYPE_MULTI){
                    $couponPrize = $money * $rule[$ruleIdx]['prize'];//倍数
                }else{
                    $couponPrize = amount_format($rule[$ruleIdx]['prize'], true);//固定金额
                }
                if(isset($rule[$ruleIdx]['upper_limit']) && $rule[$ruleIdx]['upper_limit'] > 0){
                    $upperLimit = amount_format($rule[$ruleIdx]['upper_limit'], true);
                    $couponPrize = $couponPrize > $upperLimit ? $upperLimit : $couponPrize;//优惠金额上限
                }
            }
            //打码量 (常态打码量  优惠打码量)
            $withdrawValidbet = 0;
            $withdrawCouponValidbet = 0;
            $userLevelInfo = UserLevelService::getInfoById($user['level_id']);
            $validbetMulti = static::RECHARGE_TYPE_OFFLINE ? $userLevelInfo['deposit_offline_validbet_multi'] : $userLevelInfo['deposit_online_validbet_multi'];
            if($withdrawType == ActiveEnum::WITHDRAW_REQUIRE_TYPE_MULTI){//倍数
                $withdrawValidbet = $money * $validbetMulti;
                $withdrawCouponValidbet = ($couponPrize + $money) * $withdrawVal;
            }elseif($withdrawType == ActiveEnum::WITHDRAW_REQUIRE_TYPE_AMOUNT){//固定值
                $withdrawValidbet = $money * $validbetMulti;
                $withdrawCouponValidbet = amount_format($withdrawVal, true);
            }

            return [
                'coupon_amount' => $couponPrize, //优惠金额
                'active_id' => $activeID, // 活动id ？
                'withdraw_validbet' => $withdrawValidbet, //常态打码量
                'coupon_validbet' => $withdrawCouponValidbet, //优惠打码量
                'is_new_deposit' => $isNewDeposit, //是否首存
            ];
        }

    }
    /**
     * 判断活动是否修改
     * @param $type
     * @param $user
     * @param $activeID
     * @param $activeMoney
     * @param $activePrize
     * @param $activeType
     * @param string $upperLimit
     * @return bool
     * @throws CustomException
     */
    protected static function checkActive($type, $user, $activeID, $activeInfo , $activeType, $activeMoney, $activePrize, $upperLimit){
        if(is_numeric($activeID) && $activeID > 0){
            //会员状态信息
            $userAuthStatus = UserAuthStatus::where(['user_id' => $user['id']])->first();
            if($userAuthStatus['is_refuse_coupon'] == 1){
                error_exit(SysCode::ACTIVE_STATUS_ERROR, '会员不能享受此优惠');
            }
            $active = static::getRechargeActive($activeID);
            if(empty($active)){
                error_exit(SysCode::ACTIVE_STATUS_ERROR, '活动已经关闭');
            }

            //兼容前端享受优惠 但未达到最低充值 参数缺失问题
            if($activeMoney == null && $activePrize == null && $activeType == null && $upperLimit == null){
                return true;
            }

            //判断活动是否修改
            //获取活动信息 (金额字段已经格式化为元)
//            list($activeOffline, $activeOnline, $withdrawType, $withdrawVal) = static::getActiveInfo($activeID);
            list($activeOffline, $activeOnline, $withdrawType, $withdrawVal) = $activeInfo;
            $rule = $type == static::RECHARGE_TYPE_OFFLINE ? $activeOffline[1]['rule'] : $activeOnline[1]['rule'];


            $activeMoney = ActiveEnum::WITHDRAW_REQUIRE_TYPE_AMOUNT ? amount_format($activeMoney) : $activeMoney;
//            var_dump([$type, $rule, $activeType, $activeMoney, $activePrize, $upperLimit]);exit;

            foreach ($rule as $item) {
                if ($activeMoney == $item['money'] && $activePrize == $item['prize'] && $activeType == $item['type'] && ( ( isset($item['upper_limit']) && $upperLimit == $item['upper_limit'] ) || ( !isset($item['upper_limit']) && empty($upperLimit) ) )) {
                    return true;
                    break;
                }
            }
            error_exit(SysCode::ACTIVE_STATUS_ERROR, '充值活动已修改,请重新刷新页面');
        }
    }

    protected static function checkUserLevelRechargeLimit($type, $levelID, $money){
        $userLevelInfo = UserLevelService::getInfoById($levelID);
        if($type == 1){//线上充值
            if($money < $userLevelInfo['deposit_offline_min_limit']){
                error_exit(SysCode::RECHARGE_MONEY_ERROR, '最低入款不能少于' . amount_format($userLevelInfo['deposit_offline_min_limit']));
            }
            if($money > $userLevelInfo['deposit_offline_max_limit']){
                error_exit(SysCode::RECHARGE_MONEY_ERROR, '最高入款不能大于' . amount_format($userLevelInfo['deposit_offline_max_limit']));
            }
        }else{//其它入款统一认为是线上入款
            if($money < $userLevelInfo['deposit_online_min_limit']){
                error_exit(SysCode::RECHARGE_MONEY_ERROR, '最低入款不能少于' . amount_format($userLevelInfo['deposit_online_min_limit']));
            }
            if($money > $userLevelInfo['deposit_online_max_limit']){
                error_exit(SysCode::RECHARGE_MONEY_ERROR, '最高入款不能大于' . amount_format($userLevelInfo['deposit_online_max_limit']));
            }
        }
    }
}